<template>
  <doc-alert title="WebSocket 实时通信" url="https://doc.iocoder.cn/websocket/" />

  <div class="flex h-screen">
    <!-- 左侧：用户列表 -->
    <el-card class="w-1/4" shadow="always">
      <template #header>
        <div class="card-header">
          <span>在线用户</span>
          <el-tag :color="getTagColor" class="ml-2">{{ status }}</el-tag>
        </div>
      </template>
      <div class="user-list-container">
        <div class="user-list">
          <div v-for="user in onlineUsers" :key="user.id" class="user-item">
            <el-avatar :size="40" :src="user.avatar || '/src/assets/images/avatar.png'" />
            <div class="user-info">
              <span class="username">{{ user.nickname }}</span>
              <span class="status online" v-if="user.online">在线</span>
              <span class="status offline" v-else>离线</span>
            </div>
          </div>
        </div>
      </div>
    </el-card>

    <!-- 中间：聊天区域 -->
    <el-card class="w-2/4" shadow="always">
      <template #header>
        <div class="card-header">
          <span>聊天室</span>
          <span v-if="currentChatUser" class="ml-2">与 {{ currentChatUser.nickname }} 的对话</span>
        </div>
      </template>
      <div class="chat-container">
        <div ref="messagesContainer" class="messages">
          <div v-for="(msg, index) in messageList" :key="index"
               :class="['message', msg.fromUserId === currentUserId ? 'sent' : 'received']">
            <div class="message-content">
              <div class="message-sender" v-if="msg.fromUserId !== currentUserId">
                {{ getUserName(msg.fromUserId) }}
              </div>
              <div class="message-text">{{ msg.text }}</div>
              <div class="message-time">{{ formatTime(msg.time) }}</div>
            </div>
          </div>
        </div>
      </div>
      <div class="message-input">
        <el-input
          v-model="sendText"
          :autosize="{ minRows: 2, maxRows: 4 }"
          :disabled="!getIsOpen || !currentChatUser"
          placeholder="输入消息..."
          type="textarea"
          @keyup.enter="handlerSend"
        />
        <div class="input-actions">
          <el-button-group>
            <el-button :disabled="!getIsOpen" @click="toggleConnectStatus">
              {{ getIsOpen ? '断开连接' : '连接' }}
            </el-button>
            <el-button :disabled="!getIsOpen || !currentChatUser" type="primary" @click="handlerSend">
              发送
            </el-button>
          </el-button-group>
        </div>
      </div>
    </el-card>

    <!-- 右侧：连接和设置 -->
    <el-card class="w-1/4" shadow="always">
      <template #header>
        <div class="card-header">
          <span>设置</span>
        </div>
      </template>
      <div class="settings">
        <el-input v-model="server" disabled>
          <template #prepend>服务地址</template>
        </el-input>

        <div class="mt-4">
          <el-select v-model="currentUserId" class="w-full" placeholder="选择你的身份">
            <el-option
              v-for="user in userList"
              :key="user.id"
              :label="user.nickname"
              :value="user.id"
            />
          </el-select>
        </div>

        <div class="mt-4">
          <el-select v-model="sendUserId" class="w-full" placeholder="选择聊天对象">
            <el-option key="all" label="所有人" value="" />
            <el-option
              v-for="user in filteredUserList"
              :key="user.id"
              :label="user.nickname"
              :value="user.id"
            />
          </el-select>
        </div>

        <div class="mt-4">
          <el-button type="info" @click="clearMessages">清空聊天记录</el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script lang="ts" setup>
import { formatDate } from '@/utils/formatTime'
import { useWebSocket } from '@vueuse/core'
import { getRefreshToken } from '@/utils/auth'
import * as UserApi from '@/api/system/user'
import { nextTick, onMounted, ref, watch, computed } from 'vue'

defineOptions({ name: 'ChatRoom' })

const message = useMessage()
const messagesContainer = ref<HTMLElement | null>(null)

// WebSocket 配置
const server = ref(
  (import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
  '?token=' +
  getRefreshToken()
)

// 状态管理
const { status, data, send, close, open } = useWebSocket(server.value, {
  autoReconnect: true,
  heartbeat: true
})

const getIsOpen = computed(() => status.value === 'OPEN')
const getTagColor = computed(() => (getIsOpen.value ? 'success' : 'red'))

// 修复第二个问题：替换 v-for 中的 v-if
const filteredUserList = computed(() => {
  return userList.value.filter(user => user.id !== currentUserId.value)
})

// 用户管理
const userList = ref<any[]>([])
const onlineUsers = ref<any[]>([])
const currentUserId = ref('')
const sendUserId = ref('')
const currentChatUser = computed(() =>
  sendUserId.value ? userList.value.find(u => u.id === sendUserId.value) : null
)

// 消息管理
const messageList = ref<Array<{
  time: number
  text: string
  fromUserId: string
  toUserId: string
}>>([])
const sendText = ref('')

// 获取用户名称
const getUserName = (userId: string) => {
  const user = userList.value.find(u => u.id === userId)
  return user ? user.nickname : '未知用户'
}

// 格式化时间
const formatTime = (timestamp: number) => {
  return formatDate(new Date(timestamp), 'HH:mm:ss')
}

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesContainer.value) {
      messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
    }
  })
}

// 处理接收到的消息
watch(data, (newData) => {
  if (!newData) return

  try {
    // 心跳消息
    if (newData === 'pong') return

    const jsonMessage = JSON.parse(newData)
    const type = jsonMessage.type
    const content = JSON.parse(jsonMessage.content)

    if (!type) {
      message.error('未知的消息类型：' + newData)
      return
    }

    // 用户状态更新
    if (type === 'user-status-update') {
      onlineUsers.value = userList.value.map(user => ({
        ...user,
        online: content.onlineUserIds.includes(user.id)
      }))
      return
    }

    // 聊天消息
    if (type === 'chat-message') {
      messageList.value.push({
        text: content.text,
        time: new Date().getTime(),
        fromUserId: content.fromUserId,
        toUserId: content.toUserId
      })
      scrollToBottom()
      return
    }

    message.error('未处理消息：' + newData)
  } catch (error) {
    console.error('处理消息发生异常：', error)
    message.error('处理消息发生异常：' + newData)
  }
})

// 发送消息
const handlerSend = () => {
  if (!sendText.value.trim()) return
  if (!currentUserId.value) {
    message.warning('请先选择你的身份')
    return
  }

  const messageContent = JSON.stringify({
    text: sendText.value,
    fromUserId: currentUserId.value,
    toUserId: sendUserId.value
  })

  const jsonMessage = JSON.stringify({
    type: 'chat-message',
    content: messageContent
  })

  send(jsonMessage)

  // 如果是私聊，本地也显示发送的消息
  if (sendUserId.value) {
    messageList.value.push({
      text: sendText.value,
      time: new Date().getTime(),
      fromUserId: currentUserId.value,
      toUserId: sendUserId.value
    })
    scrollToBottom()
  }

  sendText.value = ''
}

// 切换连接状态
const toggleConnectStatus = () => {
  if (getIsOpen.value) {
    close()
  } else {
    open()
  }
}

// 清空消息
const clearMessages = () => {
  messageList.value = []
}

// 初始化
onMounted(async () => {
  userList.value = await UserApi.getSimpleUserList()
  onlineUsers.value = userList.value.map(user => ({ ...user, online: false }))

  // 默认选择第一个用户
  if (userList.value.length > 0) {
    currentUserId.value = userList.value[0].id
  }
})

// 监听用户选择变化
watch(currentUserId, (newVal) => {
  if (newVal) {
    // 可以在这里发送用户上线通知
    const messageContent = JSON.stringify({
      userId: newVal,
      online: true
    })

    const jsonMessage = JSON.stringify({
      type: 'user-status',
      content: messageContent
    })

    send(jsonMessage)
  }
})
</script>

<style scoped>
.user-list {
  height: calc(100% - 60px);
  overflow-y: auto;
}

.user-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  transition: background-color 0.3s;
}

.user-item:hover {
  background-color: #f5f5f5;
}

.user-info {
  margin-left: 10px;
  display: flex;
  flex-direction: column;
}

.username {
  font-weight: 500;
}

.status {
  font-size: 12px;
  margin-top: 2px;
}

.online {
  color: #67c23a;
}

.offline {
  color: #909399;
}

.chat-container {
  height: calc(100% - 160px);
  display: flex;
  flex-direction: column;
}

.messages {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}

.message {
  margin-bottom: 15px;
  display: flex;
}

.message.sent {
  justify-content: flex-end;
}

.message.received {
  justify-content: flex-start;
}

.message-content {
  max-width: 70%;
  padding: 10px 15px;
  border-radius: 18px;
  position: relative;
}

.message.sent .message-content {
  background-color: #409eff;
  color: white;
  border-top-right-radius: 0;
}

.message.received .message-content {
  background-color: #f5f5f5;
  border-top-left-radius: 0;
}

.message-sender {
  font-size: 12px;
  color: #666;
  margin-bottom: 4px;
}

.message-time {
  font-size: 10px;
  text-align: right;
  margin-top: 4px;
  opacity: 0.7;
}

.message.sent .message-time {
  color: rgba(255, 255, 255, 0.7);
}

.message-input {
  margin-top: 20px;
}

.input-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.settings {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.user-list {
  min-height: 100%;
}

.user-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  transition: background-color 0.3s;
}

.user-item:hover {
  background-color: #f5f5f5;
}
</style>
